using System;
using System.Collections.Generic;

namespace Glue.Internals.Verification
{
    internal class AssertMapsCorrectly
    {
        private readonly IEnumerable<IRelation> relations;
        private readonly object toObject;
        private readonly Func<IRelation, IObjectMember> getFromPropertyInfo;
        private readonly Func<IRelation, IObjectMember> getToPropertyInfo;
        private readonly AssertMapsCorrectlyParameters parameters;

        public AssertMapsCorrectly(IEnumerable<IRelation> relations, object toObject, AssertMapsCorrectlyParameters parameters)
        {
            this.relations = relations;
            this.toObject = toObject;
            this.parameters = parameters;
            getFromPropertyInfo = parameters.GetFromPropertyInfo;
            getToPropertyInfo = parameters.GetToPropertyInfo;
        }

        public void Assert()
        {
            var failedProperties = new List<String>();
            foreach (var relation in relations)
            {
                var fromPropertyInfo = getFromPropertyInfo(relation);
                var toPropertyInfo = getToPropertyInfo(relation);

                var relationMapper = new AssertMapsPropertyCorrectly(relation, fromPropertyInfo, toPropertyInfo, toObject, parameters);
                if (!relationMapper.Map())
                    failedProperties.Add(relationMapper.ErrorMessage);
            }
            if (failedProperties.Count > 0)
                throw new GlueException("Failed properties: " + BuildString(failedProperties));
        }

        private String BuildString(IEnumerable<string> members)
        {
            var errorMessage = "";
            foreach (var member in members)
            {
                errorMessage += member + ",";
            }
            return errorMessage.Substring(0, errorMessage.Length - 1);
        }
    }
}